Skip to content

Elasticsearch 的 Dynamic Field Mapping 注意事項

TLDR

  • 正式環境強烈建議使用 Explicit Mapping(明確對應),避免使用 Dynamic Mapping。
  • 動態對應會自動將字串建立為 textkeyword 雙重索引,導致儲存空間大幅膨脹。
  • 特殊型別(如 geo_pointnested)與自訂分析器無法透過動態對應自動處理,必須手動定義。
  • 動態對應容易引發 Mapping Explosion,導致欄位數量超過預設限制(1000 個),進而影響記憶體與效能。
  • 建議根據需求調整 dynamic 參數:開發期可用 true,正式環境建議視情況改為 falsestrict

動態欄位對應的誤區與風險

Elasticsearch 的 Dynamic Mapping 功能雖然方便,但在生產環境中隱藏了許多潛在問題。以下分析常見的踩雷情境與原因:

1. 字串型別導致儲存空間膨脹

什麼情況下會遇到: 當系統自動將字串欄位建立索引時。

  • 原因分析:預設情況下,Elasticsearch 會將字串同時儲存為 text(用於全文檢索)與 keyword(用於精確比對、排序與聚合)的子欄位。這種雙重索引會導致儲存空間倍增。
  • 建議做法:若非必要,應明確定義欄位型別,避免不必要的索引開銷。

2. 進階功能無法自動對應

什麼情況下會遇到: 當需要使用地理查詢、巢狀物件或自訂分詞時。

  • 原因分析
    • 地理位置:若未預先定義為 geo_pointgeo_shape,資料會被視為普通 object,導致無法使用 geo_distance 等地理查詢功能。
    • 巢狀物件:動態對應會將陣列物件扁平化為 object,導致無法正確查詢陣列內部的獨立物件。
    • 自訂分析器:動態對應僅會使用預設的 standard analyzer,無法套用中文分詞或同義詞處理。
  • 建議做法:針對特定查詢需求,必須在 Mapping 中明確指定型別與 analyzer

3. Mapping Explosion 風險

什麼情況下會遇到: 當資料來源包含大量動態產生的 Key 或使用者自訂欄位時。

  • 原因分析:動態對應會不斷新增欄位到 Index 中,若欄位數量超過預設的 1000 個限制,系統將拒絕寫入新文件,並導致記憶體使用量激增。
  • 建議做法:對於結構不固定的資料,應考慮使用 falsestrict 設定來限制自動對應。

Dynamic Mapping 型別對應規則

Elasticsearch 根據 JSON 資料型別進行自動對應的規則如下:

JSON 資料型別Elasticsearch 型別 ("dynamic":"true")Elasticsearch 型別 ("dynamic":"runtime")
null不新增欄位不新增欄位
truefalsebooleanboolean
doublefloatdouble
longlonglong
objectobject不新增欄位
array取決於陣列中第一個非 null取決於陣列中第一個非 null
通過日期檢測的 stringdatedate
通過數字檢測的 stringfloatlongdoublelong
未通過 datenumeric 檢測的 stringtext 並帶有 .keyword 子欄位keyword

Dynamic 參數設定建議

透過設定 dynamic 參數,可以有效控制 Index 的結構安全性:

  • true (預設值):新欄位自動加入 Mapping。僅適合開發階段快速測試。
  • runtime:新欄位以 Runtime fields 加入,不佔用索引空間,但查詢效能較差,適合不常查詢的欄位。
  • false:忽略新欄位。欄位不會被索引或搜尋,但仍存在於 _source 中。可有效防止 Mapping Explosion。
  • strict:最嚴格模式。偵測到新欄位即拋出例外並拒絕寫入,適合需要嚴格 Schema 控制的正式環境。

總結

在正式環境中,應避免過度依賴 Dynamic Mapping。事先規劃並明確定義 Schema,不僅能優化儲存空間與查詢效能,還能避免日後因 Mapping 變更而必須進行昂貴的 Reindex 操作。


異動歷程

    • 初版文件建立。